using System;
using System.Collections;
using System.Collections.Generic;

namespace TestCases.Tests.Helpers
{
    public class TestTypes
    {
        public interface IAncestor
        {
        }

        public class Ancestor: IAncestor
        {            
        }

        public class Descendant: Ancestor
        {            
        }

        public interface IGenericInterface<T>
        {            
        }

        public interface IAnotherInterface<T>
        {            
        }

        public interface ISimpleInterface
        {            
        }

        public class ComparableClass: IComparable
        {
            public int Value { get; set; }
            public int CompareTo(object obj)
            {
                return Value.CompareTo(((ComparableClass) obj).Value);
            }
        }

        public class TestClass:                         
            IGenericInterface<Descendant>, 
            IGenericInterface<string>, 
            IGenericInterface<Ancestor>, 
            IAnotherInterface<Descendant>,
            ISimpleInterface,
            IGenericInterface<IAncestor>
        {
        }


        public class TestLeft:
            IGenericInterface<IAncestor>,
            IGenericInterface<Ancestor>,
            IGenericInterface<Descendant>,
            IGenericInterface<string>,
            IAnotherInterface<Descendant>,
            ISimpleInterface
        {            
        }

        public class TestRight :
            IGenericInterface<Ancestor>,
            IGenericInterface<Descendant>,
            IGenericInterface<string>,
            IAnotherInterface<IAncestor>,
            ISimpleInterface            
            
        {            
        }

        public class CircularReferencesClass
        {
            public CircularReferencesClass ReferencesToThis { get; set; }
        }
        
        public class Comparer: IComparer
        {
            private readonly bool _safe;

            public Comparer(bool safe)
            {
                _safe = safe;
            }

            public int Compare(object x, object y)
            {
                if (!_safe)
                {
                    return ((IComparable) x).CompareTo(y);
                }
                
                if (x is IComparable)
                {
                    return ((IComparable) x).CompareTo(y);
                }
                if (y is IComparable)
                {
                    return -((IComparable) y).CompareTo(x);
                }
                return -1;
            }
        }
        
        public class GenericComparer<T>: IComparer<T>
        {
            public int Compare(T x, T y)
            {
                if (x is IComparable<T>)
                {
                    return ((IComparable<T>) x).CompareTo(y);
                }
                if (y is IComparable<T>)
                {
                    return -((IComparable) y).CompareTo(x);
                }
                return -1;
            }
        }
        
        public class EqualityComparer: IEqualityComparer
        {
            public new bool Equals(object x, object y)
            {
                return x.Equals(y);
            }

            public int GetHashCode(object obj)
            {
                return obj.GetHashCode();
            }
        }
        
        public class EqualityGenericComparer<T>: IEqualityComparer<T>
        {
            public bool Equals(T x, T y)
            {
                return x.Equals(y);
            }

            public int GetHashCode(T obj)
            {
                return obj.GetHashCode();
            }
        }
        
        public class EmptyClass
        {            
        }
        
        public class PropertiesClass
        {
            private readonly int _readOnlyValue;

            public PropertiesClass(int readOnlyValue)
            {
                _readOnlyValue = readOnlyValue;
            }

            public string StringValue1 { get; set; }
            
            public int ReadOnlyValue 
            { 
                get
                {
                    return _readOnlyValue;
                }
            }
            
            private string PrivateValue
            {
                get
                {
                    return StringValue1;
                }
                set
                {
                    StringValue1 = value;
                }
            }
            
            public int this[int index]
            {
                get
                {
                    return ReadOnlyValue;
                }
            }

            public string this[string x]
            {
                get
                {
                    return StringValue1;
                }
                set
                {
                    StringValue1 = value;
                }
            }
            
        }

        public class PropertiesClass2 : PropertiesClass
        {
            public PropertiesClass2(int readOnlyValue) : base(readOnlyValue)
            {
            }
            public string StringValue2 { get; set; }
        }
        
        public class FieldsClass
        {
            public FieldsClass(string stringValue, string privateValue)
            {
                StringValue1 = stringValue;
                _privateValue = privateValue;
            }
            public string StringValue1;
            private string _privateValue;         
        }
        
        public class FieldsClass2: FieldsClass
        {
            public FieldsClass2(string stringValue, string stringValue2, string privateValue): base(stringValue, privateValue)
            {
                StringValue2 = stringValue2;
            }
            public string StringValue2;
        }

        public class EqualsToClass1
        {
            public int TestValue { get; set; }
            public override bool Equals(object obj)
            {
                if (obj is EqualsToClass1)
                {
                    return TestValue == ((EqualsToClass1) obj).TestValue;
                }
                return false;
            }
            public override int GetHashCode()
            {
                return TestValue;
            }
        }

        public class EqualsToClass2
        {
            public int TestValue { get; set; }
            public override bool Equals(object obj)
            {
                if (obj is EqualsToClass1)
                {
                    return TestValue == ((EqualsToClass1) obj).TestValue;
                }
                if (obj is EqualsToClass2)
                {
                    return TestValue == ((EqualsToClass2) obj).TestValue;
                }
                return false;
            }
            public override int GetHashCode()
            {
                return TestValue;
            }
        }
    }
}